#include "logic.h"

Logic::Logic(agr_user *user){
	this->user = user;
	this->fileHandler = 0;
}
             
std::vector<agr_user*> Logic::getUserList()
{ 
	return this->userList; 
}

void Logic::addUser(agr_user *user){ 
	userList.push_back(user); 
};

agr_user *Logic::getUser()
{ 
	return this->user;
}

void Logic::removeUser(agr_user *user)
{
	for(int i = 0; i < this->userList.size(); i++){
		if(this->userList[i] == user)
		{
			this->userList.erase(userList.begin() + i);
		}
	}
}

agr_file *Logic::createFile(char *path){
	// --------------------------------- //
	// -----    TODO: AGR_HANDLE   ----- //  
	// ----- TODO: OVERWRITE CHECK ----- //
	// --------------------------------- //

	FILE *fp = fopen(path, "w+b");
	if(!fp)
		return 0;
	fclose(fp);

	agr_file *file = new agr_file();
	memset(file, 0, sizeof(agr_file));
	file->init();
	file->lock();
		strcpy(file->path, path);
		file->handlerID = this->fileHandler++;
		file->owner = this->user;
	file->unlock();

	return file;
}

agr_file *Logic::openFile(char *path){
	agr_file *file = new agr_file();
	memset(file, 0, sizeof(agr_file));
	file->init();
	file->lock();

	file->handle = fopen(path, "rb");
	if(!file->handle){
		delete file;
		return NULL;
	}
	
	fseek(file->handle, 0, SEEK_END);
	file->size = ftell(file->handle);
	rewind(file->handle);

	fclose(file->handle);

	strcpy(file->path, path);
	file->handlerID = this->fileHandler++;

	file->unlock();

	return file;
}

bool Logic::fileInflate(agr_file* file, u64 size){
	if(file == NULL)
		return false;

	EnterCriticalSection(&(file->csLock));

	file->handle = fopen(file->path, "wb");
	if(file->handle == NULL){
		file->unlock();
		return false;
	}

	file->size = size;

	u8 dummy = 0x00;
	fseek(file->handle, size, SEEK_SET);
	fwrite(&dummy, 1, 1, file->handle);

	fclose(file->handle);

	return true;
}

bool Logic::readFileChunks(agr_file *file){
	if(file == NULL)
		return false;

	EnterCriticalSection(&(file->csLock));

	char path[1030] = {0};
	strcpy(path, file->path);
	strcat(path, ".chunk");

	file->handle = fopen(path, "rb");
	if(file->handle == NULL){
		file->unlock();
		return true;
	}

	fseek(file->handle, 0, SEEK_END);
	int elements = ftell(file->handle) / sizeof(chunk_s);
	rewind(file->handle);

	
	while(elements > 0){
		chunk_s chunkInfo;
		fread(&chunkInfo, sizeof(chunk_s), 1, file->handle);

		agr_chunk *chunk = new agr_chunk();
		memset(chunk, 0, sizeof(agr_chunk));
		chunk->status = (chunk_status)chunkInfo.status;
		chunk->offset = chunkInfo.offset;
		chunk->size = chunkInfo.size;

		if(chunk->status >= CHUNK_CORRUPT)
			chunk->status = CHUNK_CORRUPT;

		file->fileChunks.push_back(chunk);

		elements--;
	}

	file->unlock();

	return true;
}

bool Logic::detectFiles(){
	DIR *dir = opendir("C:\\Agora\\");
	if(!dir){
		// ---------------------------- //
		// ----- TODO: CREATE DIR ----- //
		// ---------------------------- //

	}

	dirent *dfile = NULL;

	while((dfile = readdir(dir)) != NULL){

		if(strcmp(dfile->d_name, ".") == 0 || strcmp(dfile->d_name, "..") == 0)
			continue;
	
		int len = strlen(dfile->d_name);
		if(	dfile->d_name[--len] == 'k' &&
			dfile->d_name[--len] == 'n' &&
			dfile->d_name[--len] == 'u' &&
			dfile->d_name[--len] == 'h' &&
			dfile->d_name[--len] == 'c' &&
			dfile->d_name[--len] == '.')
			continue;

		char path[1024] = {0};
		strcpy(path, "C:\\Agora\\");
		strcat(path, dfile->d_name);
		
		agr_file *file = openFile(path);
		if(!file)
			return false;
		
		if(!readFileChunks(file)){
			delete file;
			return false;
		}

		file->lock();
			file->owner = this->user;
			this->user->filesList.push_back(file);
		file->unlock();
	}

	return true;
}
